﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace 不规则三角网体积计算
{
    public partial class MDIParent1 : Form
    {
        public MDIParent1()
        {
            InitializeComponent();
        }

        private void OpenFile(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                openFileDialog.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";
                if (openFileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    using (StreamReader sr = new StreamReader(openFileDialog.FileName))
                    {
                        string line = null;
                        int i = 0;
                        int n = 0;
                        while ((line = sr.ReadLine()) != null)
                        {
                            if (i == 0)
                            {
                                string[] s = line.Split(',');
                                txtH.Text = s[1];
                                i++;
                            } else if (i == 1)
                            {
                                i++;
                            }
                            else
                            {
                                string[] s = line.Split(',');
                                int index = dataGridView1.Rows.Count;
                                if (n >= index - 1)
                                {
                                    dataGridView1.Rows.AddCopy(index - 1);
                                }
                                dataGridView1.Rows[n].Cells[0].Value = s[0];
                                dataGridView1.Rows[n].Cells[1].Value = s[1];
                                dataGridView1.Rows[n].Cells[2].Value = s[2];
                                dataGridView1.Rows[n++].Cells[3].Value = s[3];
                            }

                        }
                    }
                }
                tool.Text = "文件打开成功！";
            }
            catch
            {
                tool.Text = "文件打开失败，请查看数据格式！";
            }
        }

        private void ExitToolsStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ToolBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toolStrip.Visible = toolBarToolStripMenuItem.Checked;
        }

        private void StatusBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            statusStrip.Visible = statusBarToolStripMenuItem.Checked;
        }

        List<Triangle> T1 = new List<Triangle>();//三角形
        List<double> Vsort = new List<double>();//体积
        double Vsum = 0.0;
        private void btnJS_Click(object sender, EventArgs e)
        {
            try
            {
                T1.Clear();
                Vsort.Clear();
                List<string> Id = new List<string>();//点号
                List<double> X = new List<double>();//x坐标
                List<double> Y = new List<double>();//y坐标
                List<double> Z = new List<double>();//z坐标

                for (int i = 0; i < dataGridView1.Rows.Count; i++)
                {
                    if (dataGridView1.Rows[i].Cells[1].Value != null)
                    {
                        Id.Add(dataGridView1.Rows[i].Cells[0].Value.ToString());
                        X.Add(double.Parse(dataGridView1.Rows[i].Cells[1].Value.ToString()));
                        Y.Add(double.Parse(dataGridView1.Rows[i].Cells[2].Value.ToString()));
                        Z.Add(double.Parse(dataGridView1.Rows[i].Cells[3].Value.ToString()));
                    }
                }
                double Xmin = X.Min();
                double Xmax = X.Max();
                double Ymin = Y.Min();
                double Ymax = Y.Max();
                Point p1 = new Point("p1", Xmin - 1, Ymin - 1, 0);
                Point p2 = new Point("p2", Xmin - 1, Ymax + 1, 0);
                Point p3 = new Point("p3", Xmax + 1, Ymax + 1, 0);
                Point p4 = new Point("p4", Xmax + 1, Ymin - 1, 0);


                T1.Add(new Triangle(p2, p1, p3, 0));//添加初始三角形
                T1.Add(new Triangle(p4, p1, p3, 0));

                List<Point> point = new List<Point>();
                for (int i = 0; i < X.Count; i++)
                {
                    point.Add(new Point(Id[i], X[i], Y[i], Z[i]));//点
                }

                for (int i = 0; i < point.Count; i++)//循环点
                {
                    List<Edge> edge = new List<Edge>();//储存边
                    for (int j = 0; j < T1.Count; j++)
                    {
                        //计算圆心坐标和半径
                        double[] x0y0r = X0Y0R(T1[j].p1.x, T1[j].p1.y, T1[j].p2.x, T1[j].p2.y, T1[j].p3.x, T1[j].p3.y);
                        //计算点到圆心的距离
                        double Dis = Math.Sqrt((point[i].x - x0y0r[0]) * (point[i].x - x0y0r[0]) + (point[i].y - x0y0r[1]) * (point[i].y - x0y0r[1]));

                        if (Dis < x0y0r[2])
                        {
                            edge.Add(new Edge(T1[j].p1, T1[j].p2));
                            edge.Add(new Edge(T1[j].p2, T1[j].p3));
                            edge.Add(new Edge(T1[j].p3, T1[j].p1));
                            T1[j].B = false;
                        }
                    }
                    for (int j = T1.Count - 1; j >= 0; j--)//删除不满足三角形
                    {
                        if (T1[j].B == false)
                        {
                            T1.RemoveAt(j);
                        }
                    }

                    for (int j = 0; j < edge.Count; j++)//删除重复边
                    {
                        for (int n = j + 1; n < edge.Count; n++)
                        {
                            if ((edge[j].p1 == edge[n].p1 && edge[j].p2 == edge[n].p2) || (edge[j].p2 == edge[n].p1 && edge[j].p1 == edge[n].p2))
                            {
                                edge[j].B = false;
                                edge[n].B = false;
                            }
                        }
                    }

                    for (int j = 0; j < edge.Count; j++)//组成新三角形
                    {
                        if (edge[j].B == true)
                        {
                            T1.Add(new Triangle(edge[j].p1, edge[j].p2, point[i], 0));
                        }
                    }
                }

                for (int i = 0; i < T1.Count; i++)//与原始三角形相关的
                {
                    if (T1[i].p1 == p1 || T1[i].p2 == p1 || T1[i].p3 == p1)
                    {
                        T1[i].B = false;
                    }
                    else if (T1[i].p1 == p2 || T1[i].p2 == p2 || T1[i].p3 == p2)
                    {
                        T1[i].B = false;
                    }
                    else if (T1[i].p1 == p3 || T1[i].p2 == p3 || T1[i].p3 == p3)
                    {
                        T1[i].B = false;
                    }
                    else if (T1[i].p1 == p4 || T1[i].p2 == p4 || T1[i].p3 == p4)
                    {
                        T1[i].B = false;
                    }
                }

                for (int i = T1.Count - 1; i >= 0; i--)
                {
                    if (T1[i].B == false)
                    {
                        T1.RemoveAt(i);
                    }
                }
                double H0 = double.Parse(txtH.Text);//设计高程

                for (int i = 0; i < T1.Count; i++)
                {
                    double area = Area(T1[i].p1.x, T1[i].p1.y, T1[i].p2.x, T1[i].p2.y, T1[i].p3.x, T1[i].p3.y);
                    double H = (T1[i].p1.z + T1[i].p2.z + T1[i].p3.z) / 3.0 - H0;
                    double V = area * H;
                    Vsort.Add(V);
                    T1[i].V = V;
                }
                Vsort.Sort();//排序
                for (int i = 0; i < T1.Count; i++)
                {
                    Vsum += T1[i].V;
                }
                for (int i = 0; i < T1.Count; i++)
                {
                    int index = dataGridView2.Rows.Count;
                    if (i >= index - 1)
                    {
                        dataGridView2.Rows.AddCopy(index - 1);
                    }
                    dataGridView2.Rows[i].Cells[0].Value = i + 1;
                    dataGridView2.Rows[i].Cells[1].Value = T1[i].p1.Id;
                    dataGridView2.Rows[i].Cells[2].Value = T1[i].p2.Id;
                    dataGridView2.Rows[i].Cells[3].Value = T1[i].p3.Id;
                    dataGridView2.Rows[i].Cells[4].Value = Math.Round(T1[i].V, 4);
                }
                tool.Text = "计算成功！";
            }
            catch
            {
                tool.Text = "计算失败，请查看数据格式！";
            }
           
        }
        /// <summary>
        /// 报告
        /// </summary>
        /// <returns></returns>
        public string Report()
        {
            string s = null;
            if (dataGridView2.Rows[0].Cells[1].Value  != null)
            {
                s += "三角网计算\r\n";
                s += "--------------------------------基本信息--------------------------------\r\n";
                s += "基准高程：" + txtH.Text + "m\r\n";
                s += "三角形个数：" + (dataGridView2.Rows.Count - 1) + "\r\n";
                s += "体积：" + Math.Round(Vsum, 4) + "\r\n";
                s += "--------------------------------20个三角形说明--------------------------------\r\n";
                s += string.Format("{0,-20}", "序号") + string.Format("{0,-20}", "三个顶点") + "\r\n";
                for (int i = 0;i < 20;i++)
                {
                    s += string.Format("{0,-20}", dataGridView2.Rows[i].Cells[0].Value.ToString()) + string.Format("{0,-5}", dataGridView2.Rows[i].Cells[1].Value.ToString()) + string.Format("{0,-5}", dataGridView2.Rows[i].Cells[2].Value.ToString()) + string.Format("{0,-5}", dataGridView2.Rows[i].Cells[3].Value.ToString()) + "\r\n";
                }

                s += "\r\n";
                s += "--------------------------------体积最小的5个三棱柱体积--------------------------------\r\n";
                for (int i = 0;i < 5;i++)
                {
                    s += (i + 1) + ":" + Math.Round(Vsort[i],4) + "\r\n";
                }

                s += "--------------------------------体积最大的5个三棱柱体积--------------------------------\r\n";
                int n = 1;
                for (int i = Vsort.Count-1; i >Vsort.Count - 6; i--)
                {
                    s += n + ":" + Math.Round(Vsort[i],4) + "\r\n";
                    n++;
                }
            }
            return s;
        }
       /// <summary>
       /// 计算面积
       /// </summary>
       /// <param name="x1"></param>
       /// <param name="y1"></param>
       /// <param name="x2"></param>
       /// <param name="y2"></param>
       /// <param name="x3"></param>
       /// <param name="y3"></param>
       /// <returns></returns>
        public double Area(double x1,double y1,double x2,double y2,double x3,double y3)
        {
            double s = Math.Abs((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)) / 2.0;
            return s;
        }
        /// <summary>
        /// 计算外接圆圆心坐标和半径
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="x3"></param>
        /// <param name="y3"></param>
        /// <returns></returns>
        public double[] X0Y0R(double x1,double y1,double x2,double y2,double x3,double y3)
        {
            double x0 = ((y2 - y1) * (y3 * y3 - y1 * y1 + x3 * x3 - x1 * x1) - (y3 - y1) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1)) / (2.0 * (x3 - x1) * (y2 - y1) - 2.0 * (x2 - x1) * (y3 - y1));
            double y0 = ((x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1) - (x3 - x1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1)) / (2.0 * (y3 - y1) * (x2 - x1) - 2.0 * (y2 - y1) * (x3 - x1));
            double r = Math.Sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
            double[] x0y0r = { x0, y0, r };
            return x0y0r;
        }

        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            if (dataGridView2.Rows[0].Cells[1].Value != null)
            {
                var frm = new Draw(T1, "三角网");
                frm.Show();
            }
            else
            {
                tool.Text = "请先进行计算!";
            }
            
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            if (dataGridView2.Rows[0].Cells[1].Value != null)
            {
                var frm = new Form1();
                frm.Show(this);
            }
            else
            {
                tool.Text = "请先进行计算!";
            }                      
        }
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            txtH.Clear();
            dataGridView1.Rows.Clear();
            dataGridView2.Rows.Clear();
            tool.Text = "清除成功！";
        }
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            try
            {

                using (StreamWriter sw = new StreamWriter(saveFileDialog1.FileName))
                {
                    string s = Report();
                    sw.WriteLine(s);
                }
                tool.Text = "文件保存成功！";
            }
            catch
            {
                tool.Text = "文件保存失败，请查看数据格式！";
            }
        }

        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
        }
    }

    /// <summary>
    /// 点类
    /// </summary>
    public  class Point
    {
        public double x;
        public double y;
        public double z;
        public string Id;
        public Point(string Id,double x,double y,double z)
        {
            this.Id = Id;
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }
    /// <summary>
    /// 边类
    /// </summary>
  public  class Edge
    {
        public Point p1;
        public Point p2;
        public bool B = true;
        public Edge(Point p1,Point p2)
        {
            this.p1 = p1;
            this.p2 = p2;
        }
    }
    /// <summary>
    /// 三角形类
    /// </summary>
   public class Triangle
    {
        public Point p1;
        public Point p2;
        public Point p3;
        public bool B = true;
        public double V;
        public Triangle(Point p1,Point p2,Point p3,double V)
        {
            this.p1 = p1;
            this.p2 = p2;
            this.p3 = p3;
            this.V = V;
        }
    }
}
